<?php
error_reporting( 0 );

if ( empty( $_SERVER[ 'REQUEST_TIME' ] ) ) $_SERVER[ 'REQUEST_TIME' ] = time();

define( 'CF_HTTP_MODE',
        isset( $_SERVER[ 'REQUEST_METHOD' ] ) && in_array( strtoupper( $_SERVER[ 'REQUEST_METHOD' ] ),
                array( 'GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH' ) ) );

$thisDirectory = dirname( __FILE__ ); //framework directory

define( 'CF_BASE_PATH',
        realpath( $thisDirectory . DIRECTORY_SEPARATOR . '..' ) . DIRECTORY_SEPARATOR );

define( 'CF_BUILD_PATH',
        realpath( $thisDirectory . DIRECTORY_SEPARATOR . 'build' ) . DIRECTORY_SEPARATOR );

unset( $thisDirectory );


//Estos errores no se verán a tráves del Log ya que todavía no hay directorio donde loguearlos
if ( !file_exists( CF_BUILD_PATH ) ){
    throw new \Exception( 'You must create a directory in \'app\' named \'build\' ' );
}

if ( !is_dir( CF_BUILD_PATH ) ){
    throw new \Exception( 'There\'s a file named \'build\' in \'app\', you must create a directory with this name. Rename or delete the file' );
}

if ( !is_readable( CF_BUILD_PATH ) || !is_writeable( CF_BUILD_PATH ) ) { //Esto no puedo hacerlo es un directorio
    $user = posix_getpwuid( posix_getuid() );

    throw new \Exception( 'The directory \'build\' doesn\'t have read or write permissions for \'' . $user[ 'name' ] . '\'' );
}


define( 'CF_CACHE_PATH', CF_BUILD_PATH . 'cache' . DIRECTORY_SEPARATOR );

if( !file_exists( CF_CACHE_PATH  ) ) {
    mkdir( CF_CACHE_PATH, 0777 );
    chmod( CF_CACHE_PATH, 0777 );
}

define( 'CF_TEMP_PATH', CF_BUILD_PATH . 'temp' . DIRECTORY_SEPARATOR );

if( !file_exists( CF_TEMP_PATH  ) ) {
    mkdir( CF_TEMP_PATH, 0777 );
    chmod( CF_TEMP_PATH, 0777 );
}





define( 'CF_LOG_ERROR', 1 );
define( 'CF_LOG_WARNING', 2 );
define( 'CF_LOG_INFO', 4 );
define( 'CF_LOG_DEBUG', 8 );
define( 'CF_LOG_TRACE', 16 );
define( 'CF_LOG_ALL', 1 | 2 | 4 | 8 | 16 );


//El ficheoro .ini lleva toda la información que necesitaremos
$_SERVER[ 'CF_INI' ] = parse_ini_file( 'copperforest.ini' );


if ( isset( $_SERVER[ 'CF_INI' ][ 'date.timezone' ] ) ) {
    date_default_timezone_set( $_SERVER[ 'CF_INI' ][ 'date.timezone' ] );
}

if ( isset( $_SERVER[ 'CF_INI' ][ 'intl.default_locale' ] ) ) {
    setlocale( LC_ALL, $_SERVER[ 'CF_INI' ][ 'intl.default_locale' ] );
}



//ahora con el default build tengo que cambiar el classpath
$_SERVER[ 'CF_BUILD' ] = 0;
    
function cfFrameworkDefaultClassPath( $className )
{


    require_once( CF_BUILD_PATH . $_SERVER[ 'CF_BUILD' ] . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . str_replace( "\\", DIRECTORY_SEPARATOR,
                    $className ) . '.class.php');
}

spl_autoload_register( 'cfFrameworkDefaultClassPath' );    




function cfErrorHandlingFunction( $errno, $errstr, $errfile, $errline )
{

    $e = new \ErrorException( $errstr, 0, $errno, $errfile, $errline );
    
    //\org\copperforest\build\Logger::getLogger( CF_LOG_ERROR )->log( $e );

    if( isset( $_SERVER[ 'CF_INI' ][ 'exception.error_level' ] ) ){
        
        if ( $errno & ( (int) $_SERVER[ 'CF_INI' ][ 'exception.error_level' ] ) ){
            throw $e;
        }
        else{
            \org\copperforest\build\Logger::getLogger( CF_LOG_ERROR )->log( $e );
        }
    }
    else if ( $errno & E_ERROR ){
        throw $e;
    }
    else{
        \org\copperforest\build\Logger::getLogger( CF_LOG_ERROR )->log( $e );
    }
}


set_error_handler( 'cfErrorHandlingFunction' );
  
//TO LOG FALTAL ERRRORS
function cfFatalErrorShutdown()
{
    $error = error_get_last();
    
    if ( $error ) {        

        $e = new \ErrorException( $error[ 'message' ], 0, $error[ 'type' ],
                $error[ 'file' ], $error[ 'line' ] );

        //l =
        \org\copperforest\build\Logger::getLogger( CF_LOG_ERROR )->log( $e );
    }
}

register_shutdown_function( 'cfFatalErrorShutdown' );

/*
if ( isset( $_SERVER[ 'CF_INI' ][ 'error_reporting' ] ) ) {
        error_reporting( $_SERVER[ 'CF_INI' ][ 'error_reporting' ] );
}
*/
//error_reporting( 0 ); 


function js_encode( $string, $charset = 'UTF-8' )
{
    $string = mb_convert_encoding($string, 'UCS-2', $charset );
    if (empty($string))
        return '';

    return "\\u" . implode("\\u", str_split(bin2hex($string), 4));
}

function base_encode( $num, $b = 62 )
{
    $base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $r = $num % $b;
    $res = $base[ $r ];
    $q = floor( $num / $b );
    while ( $q ) {
        $r = $q % $b;
        $q = floor( $q / $b );
        $res = $base[ $r ] . $res;
    }
    return $res;
}

function base_decode( $num, $b = 62 )
{
    $base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $limit = strlen( $num );
    $res = strpos( $base, $num[ 0 ] );
    for ( $i = 1; $i < $limit; $i++ ) {
        $res = $b * $res + strpos( $base, $num[ $i ] );
    }
    return $res;
}

//from http://darklaunch.com/2009/08/07/base58-encode-and-decode-using-php-with-example-base58-encode-base58-decode
function base58_encode( $num )
{
    $alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
    $base_count = strlen( $alphabet );
    $encoded = '';

    while ( $num >= $base_count ) {
        $div = $num / $base_count;
        $mod = ($num - ($base_count * intval( $div )));
        $encoded = $alphabet[ $mod ] . $encoded;
        $num = intval( $div );
    }

    if ( $num ) {
        $encoded = $alphabet[ $num ] . $encoded;
    }

    return $encoded;
}

function base58_decode( $num )
{
    $alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
    $len = strlen( $num );
    $decoded = 0;
    $multi = 1;

    for ( $i = $len - 1; $i >= 0; $i-- ) {
        $decoded += $multi * strpos( $alphabet, $num[ $i ] );
        $multi = $multi * strlen( $alphabet );
    }

    return $decoded;
}

function b64url_encode( $str )
{
    return strtr( base64_encode( $str ),
            array( '+' => '-', '/' => '_', '=' => '' ) );
}

function b64url_decode( $str )
{
    return base64_decode( strtr( $str, array( '-' => '+', '_' => '/' ) ) );
}

//nbari at dalmp dot com
function rmtree( $dir )
{
    $files = array_diff( scandir( $dir ), array( '.', '..' ) );

    foreach ( $files as $file )
            (is_dir( $dir . DIRECTORY_SEPARATOR . $file )) ? rmtree( $dir . DIRECTORY_SEPARATOR . $file ) : unlink( $dir . DIRECTORY_SEPARATOR . $file );

    return rmdir( $dir );
}

//Ondra Zizka at www.php.net/is_subclass_of
function is_subclass( $sClass, $sExpectedParentClass )
{
    do
        if ( $sExpectedParentClass === $sClass ) return true;
    while ( false != ($sClass = get_parent_class( $sClass )) );
    return false;
}

function stripslashes_deep( $value )
{
    $value = is_array( $value ) ?
            array_map( 'stripslashes_deep', $value ) :
            stripslashes( $value );

    return $value;
}

function c_uniqid( $prefix = '', $more_entropy = false )
{
    return uniqid( $prefix . php_uname( 'n' ), $more_entropy );
}

//http://www.php-security.org/2010/05/09/mops-submission-04-generating-unpredictable-session-ids-and-hashes/
function generateUniqueId( $maxLength = null )
{
    $entropy = '';

    // try ssl first
    if (function_exists('openssl_random_pseudo_bytes')) {
        $entropy = openssl_random_pseudo_bytes(64, $strong);
        // skip ssl since it wasn't using the strong algo
        if($strong !== true) {
            $entropy = '';
        }
    }

    // add some basic mt_rand/uniqid combo
    $entropy .= uniqid(mt_rand(), true);

    // try to read from the windows RNG
    /*if (class_exists('\COM')) {
        try {
            $com = new \COM('CAPICOM.Utilities.1');
            $entropy .= base64_decode($com->GetRandom(64, 0));
        } catch (Exception $ex) {
        }
    }*/

    // try to read from the unix RNG
    if (is_readable('/dev/urandom')) {
        $h = fopen('/dev/urandom', 'rb');
        $entropy .= fread($h, 64);
        fclose($h);
    }

    $hash = hash('whirlpool', $entropy);
    if ($maxLength) {
        return substr($hash, 0, $maxLength);
    }
    return $hash;
}